home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Special 26 / AMIGAplus Sonderheft 26 (2000)(Falke)(DE)(Track 1 of 2)[!].iso / Tools / GFX-Viewer / Animviewer / mpegvideo_datatype / mpegamiga.c < prev    next >
C/C++ Source or Header  |  1999-03-29  |  16KB  |  580 lines

  1.  
  2.  
  3. /*
  4. **
  5. **  $VER: mpegamiga.c 1.11 (2.11.97)
  6. **  mpegvideo.datatype 1.11
  7. **
  8. **  amiga support functions
  9. **
  10. **  Written 1996/1997 by Roland 'Gizzy' Mainz
  11. **
  12. */
  13.  
  14.  
  15. /* project includes */
  16. #include "mpegmyassert.h"
  17. #include "mpegproto.h"
  18.  
  19. /* ansi includes */
  20. #include "math.h"
  21. #include "limits.h"
  22.  
  23. /* local prototypes */
  24. static void InitStoreFrame( struct MPEGVideoInstData *mvid );
  25. static void WritePixelArray8Fast( struct BitMap *, UBYTE * );
  26.  
  27.  
  28. void mpeg_closedown( struct MPEGVideoInstData *mvid )
  29. {
  30.     if( mvid -> mvid_MPPool )
  31.     {
  32.       DeletePool( (mvid -> mvid_MPPool) );
  33.       mvid -> mvid_MPPool = NULL;
  34.     }
  35. }
  36.  
  37.  
  38. static
  39. void InitStoreFrame( struct MPEGVideoInstData *mvid )
  40. {
  41.     /* Alloc bitmap as key bitmap */
  42.     if( mvid -> mvid_UseChunkyMap )
  43.     {
  44.       mvid -> mvid_KeyBitMap = AllocBitMap( (ULONG)anim_width, (ULONG)anim_height, (ULONG)anim_depth, (BMF_CLEAR | BMF_SPECIALFMT | SHIFT_PIXFMT( pixfmt )), NULL );
  45.     }
  46.     else
  47.     {
  48.       mvid -> mvid_KeyBitMap = AllocBitMap( (ULONG)anim_width, (ULONG)anim_height, (ULONG)anim_depth, (BMF_CLEAR | BMF_MINPLANES), NULL );
  49.     }
  50.  
  51.     if( (mvid -> mvid_KeyBitMap) == NULL )
  52.     {
  53.       myexit( mvid, RETURN_FAIL, ERROR_NO_FREE_STORE );
  54.     }
  55. }
  56.  
  57.  
  58. void StoreFrame( struct MPEGVideoInstData *mvid, UBYTE *data )
  59. {
  60.     /* All ready to store the frames ? */
  61.     if( (mvid -> mvid_KeyBitMap) == NULL )
  62.     {
  63.       InitStoreFrame( mvid );
  64.     }
  65.  
  66.     switch( ditherType )
  67.     {
  68.       case HAM_DITHER:
  69.       {
  70.           ULONG *src = (ULONG *)data;
  71.           UBYTE *dest,
  72.                 *tmp;
  73.  
  74.           ULONG  height = anim_height;
  75.  
  76.           dest = tmp = (UBYTE *)mymalloc( mvid, (size_t)((anim_width + 15UL) * anim_height) );
  77.  
  78.           while( height-- )
  79.           {
  80.             UBYTE *xrgb = (UBYTE *)src;
  81.  
  82.             switch( anim_depth )
  83.             {
  84.               case 8:
  85.                   CreateHAM8Line( (xrgb + 1), (xrgb + 2), (xrgb + 3), dest, sizeof( ULONG ), anim_width );
  86.                   break;
  87.  
  88.               case 6:
  89.                   CreateHAM6Line( (xrgb + 1), (xrgb + 2), (xrgb + 3), dest, sizeof( ULONG ), anim_width );
  90.                   break;
  91.             }
  92.  
  93.             dest += anim_width;
  94.             src  += anim_width;
  95.           }
  96.  
  97.           AddFrame( mvid, tmp, NULL );
  98.  
  99.           myfree( mvid, tmp );
  100.       }
  101.           break;
  102.  
  103.       case FULL_COLOR_DITHER:
  104.       case FULL_COLOR_DITHER16:
  105.       {
  106.           AddFrame( mvid, data, NULL );
  107.       }
  108.           break;
  109.  
  110.       default:
  111.       {
  112.           struct ColorMap *cm = NULL;
  113.  
  114.           if( mvid -> mvid_PalettePerFrame )
  115.           {
  116.             if( cm = GetColorMap( (1UL << anim_depth) ) )
  117.             {
  118.               ULONG i,
  119.                     r, g, b;
  120.  
  121.               /* Copy colors into colormap... */
  122.               for( i = 0UL ; i < used_cnt ; i++ )
  123.               {
  124.                 /* Bump colors from 8 to 32 bits-per-gun */
  125.                 r = ((ULONG)used_colors[ i ] . red)   * 0x01010101UL;
  126.                 g = ((ULONG)used_colors[ i ] . green) * 0x01010101UL;
  127.                 b = ((ULONG)used_colors[ i ] . blue)  * 0x01010101UL;
  128.  
  129.                 SetRGB32CM( cm, i, r, g, b );
  130.               }
  131.  
  132.               /* Fill remaining colors with "black" */
  133.               for( ; i < (1UL << anim_depth) ; i++ )
  134.               {
  135.                 SetRGB32CM( cm, i, 0UL, 0UL, 0UL );
  136.               }
  137.             }
  138.           }
  139.  
  140.           AddFrame( mvid, data, cm );
  141.       }
  142.           break;
  143.     }
  144. }
  145.  
  146.  
  147. void AddFrame( struct MPEGVideoInstData *mvid, UBYTE *data, struct ColorMap *cm )
  148. {
  149.     ULONG             timestamp = totNumFrames++; /* timestamp of this frame */
  150.     struct FrameNode *fn;
  151.  
  152.     /* Image ? */
  153.     if( data )
  154.     {
  155.       BOOL created = FALSE;
  156.  
  157.       /* Does we have already a frame with this timestamp ? ... */
  158.       if( fn = FindFrameNode( (&(mvid -> mvid_FrameList)), timestamp ) )
  159.       {
  160.         /* ... really ? */
  161.         if( (fn -> fn_TimeStamp) != timestamp )
  162.         {
  163.           fn = NULL;
  164.         }
  165.       }
  166.  
  167.       if( fn == NULL )
  168.       {
  169.         if( mvid -> mvid_IndexScan )
  170.         {
  171.           created = TRUE;
  172.  
  173.           fn = AllocFrameNode( classbase, (mvid -> mvid_Pool) );
  174.  
  175.           if( fn && (data != (UBYTE *)~0UL) )
  176.           {
  177.             /* Create a locked frame here if new HAD to create the fn and if we have data.
  178.              * This is TRUE for the keyframe and/or of the mvid_LoadAll flag is TRUE
  179.              */
  180.             fn -> fn_IsKeyFrame = TRUE; /* lock this bitmap that ADTM_UNLOADFRAME won't free it */
  181.           }
  182.         }
  183.         else
  184.         {
  185.           myexit( mvid, RETURN_ERROR, ERROR_INVALID_LOCK );
  186.         }
  187.       }
  188.  
  189.       if( fn )
  190.       {
  191.         if( created )
  192.         {
  193.           /* Store frame count */
  194.           fn -> fn_TimeStamp =
  195.             fn -> fn_Frame   = timestamp;
  196.           fn -> fn_BMOffset  = mvid -> mvid_Last_PIC_SC_Pos;
  197.           fn -> fn_IFrame    = mvid -> mvid_LastIFrameNode;
  198.  
  199.           AddTail( (struct List *)(&(mvid -> mvid_FrameList)), (struct Node *)(&(fn -> fn_Node)) );
  200.         }
  201.  
  202.         /* Does someone wants only to create an empty framenode here (e.g. data == (UBYTE *)~0UL) ? */
  203.         if( data != (UBYTE *)~0UL )
  204.         {
  205.           if( (fn -> fn_BitMap) == NULL )
  206.           {
  207.             if( fn -> fn_BitMap = AllocFrameBitMap( mvid ) )
  208.             {
  209.               switch( ditherType )
  210.               {
  211.                 case HAM_DITHER:
  212.                 case GRAY_DITHER:
  213. #if 0
  214.                 case FAST_COLOR_DITHER:
  215. #endif
  216.                 case ORDERED_DITHER:
  217.                 {
  218.                     WritePixelArray8Fast( (fn -> fn_BitMap), data );
  219.  
  220.                     /* Store colormap */
  221.                     fn -> fn_CMap = cm;
  222.                 }
  223.                     break;
  224.  
  225.                 case FULL_COLOR_DITHER:
  226.                 case FULL_COLOR_DITHER16:
  227.                 {
  228.                     if( mvid -> mvid_UseChunkyMap )
  229.                     {
  230.                       APTR   handle;
  231.                       APTR   plane  = NULL; /* be safe ! (CyberGFX has some problems with tag parsing...) */
  232.                       ULONG  bpr    = 0UL,  /* be safe ! (CyberGFX has some problems with tag parsing...) */
  233.                              height = 0UL;  /* be safe ! (CyberGFX has some problems with tag parsing...) */
  234.  
  235.                       if( handle = LockBitMapTags( (fn -> fn_BitMap),
  236.                                                    LBMI_BASEADDRESS, (&plane),
  237.                                                    LBMI_BYTESPERROW, (&bpr),
  238.                                                    LBMI_HEIGHT,      (&height),
  239.                                                    TAG_DONE ) )
  240.                       {
  241.                         CopyMem( data, plane, (bpr * height) );
  242.  
  243.                         UnLockBitMap( handle );
  244.                       }
  245.                       else
  246.                       {
  247.                         error_printf( mvid, "LockBitMapTags failed\n" );
  248.                       }
  249.                     }
  250.                     else
  251.                     {
  252.                       if( anim_depth == 24UL )
  253.                       {
  254.                         struct BitMap red,
  255.                                       green,
  256.                                       blue;
  257.                         ULONG         i;
  258.                         UBYTE        *tmp,
  259.                                      *tmp_run;
  260.                         ULONG         size = anim_width * anim_height;
  261.  
  262.                         InitBitMap( (&red),   8, (ULONG)anim_width, (ULONG)anim_height );
  263.                         InitBitMap( (&green), 8, (ULONG)anim_width, (ULONG)anim_height );
  264.                         InitBitMap( (&blue),  8, (ULONG)anim_width, (ULONG)anim_height );
  265.  
  266.                         for( i = 0UL ; i < 24UL ; i++ )
  267.                         {
  268.                           if( i < 8  ) red   . Planes[ i      ] = fn -> fn_BitMap -> Planes[ i ]; else
  269.                           if( i < 16 ) green . Planes[ i -  8 ] = fn -> fn_BitMap -> Planes[ i ]; else
  270.                                        blue  . Planes[ i - 16 ] = fn -> fn_BitMap -> Planes[ i ];
  271.                         }
  272.  
  273.                         /* Alloc temp memory for XRGB to RRR..., GGG..., BBB... array conversion */
  274.                         tmp = mymalloc( mvid, (size_t)(size + 15UL) );
  275.  
  276.                         for( i = 0 ; i < 3 ; i++ )
  277.                         {
  278.                           ULONG j,
  279.                                 j_size = (size * 4UL) + i;
  280.  
  281.                           for( j = i, tmp_run = tmp ; j < j_size ; j += 4UL )
  282.                           {
  283.                             *tmp_run++ = data[ j ];
  284.                           }
  285.  
  286.                           switch( i )
  287.                           {
  288.                             case 0: WritePixelArray8Fast( (&red),   tmp ); break;
  289.                             case 1: WritePixelArray8Fast( (&green), tmp ); break;
  290.                             case 2: WritePixelArray8Fast( (&blue),  tmp ); break;
  291.                           }
  292.                         }
  293.  
  294.                         myfree( mvid, tmp );
  295.                       }
  296.                       else
  297.                       {
  298.                         error_printf( mvid, "unsupported planar direct-RGB depth\n" );
  299.                       }
  300.                     }
  301.                 }
  302.                     break;
  303.               }
  304.             }
  305.             else
  306.             {
  307.               /* no bitmap */
  308.               myexit( mvid, RETURN_ERROR, ERROR_NO_FREE_STORE );
  309.             }
  310.           }
  311.         }
  312.       }
  313.       else
  314.       {
  315.         /* can't alloc struct FrameNode */
  316.         myexit( mvid, RETURN_ERROR, ERROR_NO_FREE_STORE );
  317.       }
  318.     }
  319.     else
  320.     {
  321.       if( mvid -> mvid_IndexScan )
  322.       {
  323.         /* Find the nearest frame */
  324.         if( fn = FindFrameNode( (&(mvid -> mvid_FrameList)), timestamp ) )
  325.         {
  326.           /* Bump the duration time of the predecessor (frame) */
  327.           fn -> fn_Duration = timestamp - (fn -> fn_TimeStamp);
  328.         }
  329.       }
  330.     }
  331. }
  332.  
  333.  
  334.  
  335. /***************************************************************/
  336.  
  337.  
  338. static APTR  AllocVecPooled( struct MPEGVideoInstData *mvid, APTR, ULONG );
  339. static void  FreeVecPooled( struct MPEGVideoInstData *mvid, APTR, APTR );
  340. static ULONG VecSize( APTR );
  341.  
  342.  
  343. void *mymalloc( struct MPEGVideoInstData *mvid, size_t s )
  344. {
  345.     void *mem;
  346.  
  347.     if( (mvid -> mvid_MPPool) == NULL )
  348.     {
  349.       if( (mvid -> mvid_MPPool = CreatePool( (MEMF_PUBLIC | MEMF_CLEAR), 16384UL, 16384UL )) == NULL )
  350.       {
  351.         myexit( mvid, RETURN_FAIL, ERROR_NO_FREE_STORE );
  352.       }
  353.     }
  354.  
  355.     if( (mem = (void *)AllocVecPooled( mvid, (mvid -> mvid_MPPool), (ULONG)s )) == NULL )
  356.     {
  357.       myexit( mvid, RETURN_ERROR, ERROR_NO_FREE_STORE );
  358.     }
  359.  
  360.     return( mem );
  361. }
  362.  
  363.  
  364. void myfree( struct MPEGVideoInstData *mvid, void *mem )
  365. {
  366.     FreeVecPooled( mvid, (mvid -> mvid_MPPool), mem );
  367. }
  368.  
  369.  
  370. void *myrealloc( struct MPEGVideoInstData *mvid, void *oldmem, size_t newsize )
  371. {
  372.     ULONG oldsize = 0UL;
  373.     APTR  newmem  = NULL;
  374.  
  375.     if( oldmem )
  376.     {
  377.       oldsize = VecSize( oldmem );
  378.     }
  379.  
  380.     if( newsize == oldsize )
  381.     {
  382.       return( oldmem );
  383.     }
  384.  
  385.     if( newsize )
  386.     {
  387.       if( newmem = AllocVecPooled( mvid, (mvid -> mvid_MPPool), (ULONG)newsize ) )
  388.       {
  389.         if( oldsize )
  390.         {
  391.           memcpy( newmem, oldmem, (size_t)MIN( oldsize, newsize ) );
  392.         }
  393.  
  394.         FreeVecPooled( mvid, (mvid -> mvid_MPPool), oldmem );
  395.       }
  396.       else
  397.       {
  398.         myexit( mvid, RETURN_FAIL, ERROR_NO_FREE_STORE );
  399.       }
  400.     }
  401.  
  402.     return( newmem );
  403. }
  404.  
  405.  
  406. static
  407. APTR AllocVecPooled( struct MPEGVideoInstData *mvid, APTR pool, ULONG memsize )
  408. {
  409.     ULONG *memory = NULL;
  410.  
  411.     if( pool && memsize )
  412.     {
  413.       memsize += (ULONG)sizeof( ULONG );
  414.  
  415.       if( memory = (ULONG *)AllocPooled( pool, memsize ) )
  416.       {
  417.         (*memory) = memsize;
  418.         memory++;
  419.       }
  420.     }
  421.     else
  422.     {
  423.       error_printf( mvid, "AllocVecPooled: illegal args %lx %lx\n", pool, memsize );
  424.     }
  425.  
  426.     return( (APTR)memory );
  427. }
  428.  
  429.  
  430. static
  431. void FreeVecPooled( struct MPEGVideoInstData *mvid, APTR pool, APTR mem )
  432. {
  433.     if( pool && mem )
  434.     {
  435.       ULONG *memory;
  436.  
  437.       memory = (ULONG *)mem;
  438.  
  439.       memory--;
  440.  
  441.       FreePooled( pool, memory, (*memory) );
  442.     }
  443.     else
  444.     {
  445.       error_printf( mvid, "FreeVecPooled: illegal args %lx %lx\n", pool, mem );
  446.     }
  447. }
  448.  
  449.  
  450. /* get size of an AllocVecPooled memory */
  451. static
  452. ULONG VecSize( APTR mem )
  453. {
  454.     return( *(((ULONG *)mem) - 1) );
  455. }
  456.  
  457.  
  458. ULONG SearchColor( struct MPEGVideoInstData *mvid, struct ColorRegister *colortable, ULONG *numcolors, ULONG maxcount, struct ColorRegister *color )
  459. {
  460.           ULONG i;
  461.            LONG error,
  462.                 minerror      = LONG_MAX;
  463.           ULONG minerrorindex = 0UL;
  464.     const ULONG nc            = *numcolors; /* short cut to (*numcolors) (read only) */
  465.            WORD er,
  466.                 eg,
  467.                 eb;
  468.  
  469.     /* Check for a color in the specified range */
  470.     for( i = 0UL ; i < nc ; i++, colortable++ )
  471.     {
  472.       er = ABS( ((WORD)(colortable -> red)   - (WORD)(color -> red)) );
  473.       eg = ABS( ((WORD)(colortable -> green) - (WORD)(color -> green)) );
  474.       eb = ABS( ((WORD)(colortable -> blue)  - (WORD)(color -> blue)) );
  475.  
  476.       error = er + eg + eb;
  477.  
  478.       if( error < minerror )
  479.       {
  480.         if( error < (mvid -> mvid_ColorError) )
  481.         {
  482.           return( i );
  483.         }
  484.  
  485.         minerror       = error;
  486.         minerrorindex  = i;
  487.       }
  488.     }
  489.  
  490.     /* Any color entry free for this frame ? */
  491.     if( nc < maxcount )
  492.     {
  493.       *colortable = *color;
  494.  
  495.       minerrorindex = nc;
  496.  
  497.       (*numcolors)++;
  498.     }
  499.  
  500.     return( minerrorindex );
  501. }
  502.  
  503.  
  504. static
  505. void WritePixelArray8Fast( struct BitMap *dest, UBYTE *source )
  506. {
  507.     ULONG *plane[ 8 ] = { 0 },
  508.           *chunky = (ULONG *)source; /* fetch 32 bits per cycle */
  509.     ULONG  i;
  510.     ULONG  numcycles = ((dest -> Rows) * (dest -> BytesPerRow)) / sizeof( ULONG );
  511.  
  512.     /* Copy plane ptrs */
  513.     for( i = 0UL ; i < (dest -> Depth) ; i++ )
  514.     {
  515.       plane[ i ] = (ULONG *)(dest -> Planes[ i ]);
  516.     }
  517.  
  518.     /* Fill unused planes with plane 0, which will be written last, all prevoius accesses
  519.      * will be droped (assumes that a cache hides this "dummy" writes)
  520.      */
  521.     for( i ; i < 8UL ; i++ )
  522.     {
  523.       plane[ i ] = (ULONG *)(dest -> Planes[ 0 ]);
  524.     }
  525.  
  526.     /* Process bitmaps */
  527.     for( i = 0UL ; i < numcycles ; i++ )
  528.     {
  529.       ULONG tmp,
  530.             b0, b1, b2, b3, b4, b5, b6, b7;
  531.  
  532.       /* process 32 pixels */
  533.       b0 = *chunky++;  b4 = *chunky++;
  534.       b1 = *chunky++;  b5 = *chunky++;
  535.       b2 = *chunky++;  b6 = *chunky++;
  536.       b3 = *chunky++;  b7 = *chunky++;
  537.  
  538. #define merge( a, b, mask, shift ) \
  539.       tmp = mask & (a ^ (b >> shift));   \
  540.       a ^= tmp;                          \
  541.       b ^= (tmp << shift)
  542.  
  543.       merge( b0, b2, 0x0000ffff, 16 );
  544.       merge( b1, b3, 0x0000ffff, 16 );
  545.       merge( b4, b6, 0x0000ffff, 16 );
  546.       merge( b5, b7, 0x0000ffff, 16 );
  547.  
  548.       merge( b0, b1, 0x00ff00ff,  8 );
  549.       merge( b2, b3, 0x00ff00ff,  8 );
  550.       merge( b4, b5, 0x00ff00ff,  8 );
  551.       merge( b6, b7, 0x00ff00ff,  8 );
  552.  
  553.       merge( b0, b4, 0x0f0f0f0f,  4 );
  554.       merge( b1, b5, 0x0f0f0f0f,  4 );
  555.       merge( b2, b6, 0x0f0f0f0f,  4 );
  556.       merge( b3, b7, 0x0f0f0f0f,  4 );
  557.  
  558.       merge( b0, b2, 0x33333333,  2 );
  559.       merge( b1, b3, 0x33333333,  2 );
  560.       merge( b4, b6, 0x33333333,  2 );
  561.       merge( b5, b7, 0x33333333,  2 );
  562.  
  563.       merge( b0, b1, 0x55555555,  1 );
  564.       merge( b2, b3, 0x55555555,  1 );
  565.       merge( b4, b5, 0x55555555,  1 );
  566.       merge( b6, b7, 0x55555555,  1 );
  567.  
  568.       *plane[ 7 ]++ = b0;
  569.       *plane[ 6 ]++ = b1;
  570.       *plane[ 5 ]++ = b2;
  571.       *plane[ 4 ]++ = b3;
  572.       *plane[ 3 ]++ = b4;
  573.       *plane[ 2 ]++ = b5;
  574.       *plane[ 1 ]++ = b6;
  575.       *plane[ 0 ]++ = b7;
  576.     }
  577. }
  578.  
  579.  
  580.